[Part 3] Websphere Liberty Profile: OSGi, JPA, JAX-RS, and BPM

Part 3 of 4 Part Series: 

Integrating JAX-RS service with OSGi JPA data provider


Part 1: OSGi and JPA 
Part 2: ReST Services with JAX-RS 
Part 3: Integrating JAX-RS service with OSGi JPA data provider (this article)
Part 4: Integrated BPM and ReST using OSGi bundles [work-in-progress]

Forward: 
I almost gave up this exercise using Liberty... The night before I resigned myself to switching back over to Websphere Application Server. 

What held up progress was I couldn't find a work-around for service lookup via InitialContext. Websphere had this feature built-in for OSGi bundles. Liberty also... had this feature. However, I didn't see the missing critical "import-package" on the manifest:

javax.naming

With "javax.naming" in the manifest I was finally able to use the following:

(ColorManager) ic.lookup("osgi:service/"+ColorManager.class.getName()); 
- or - 
(ColorManager) ic.lookup("blueprint:comp/colormanagerservice"); <<< recommended approach

Ironically, I happened to also find another elegant workaround to Liberty's JAX-RS implementation (wink)... 

Wink created a new service class per each service request - and, consequently, didn't use the blueprint created instance. This lead to a breakage in blueprint reference injection between JAX-RS and JAP bundles:

Solution was to simply use a static property so that property value is at the class level: 

private static ColorManager colorManager = null;

The moral of the story is that, if it should work, it probably does...




OSGi and JAX-RS: Integrating JPA


1) Publish a JPA data-service with JAX-RS Service Interface (ReST)
Publish the JPA service created in previous tutorial
- Requires completion of Part 1 (see above: "Resources")

Import Interface from osgi_jpa_03 (refer to previous tutorial: "part 1: OSGI and JPA")
(refer to previous tutorial: "part 1: OSGI and JPA")

Export from JPA and then import into JAX-RS projects

Export from: osgi_jpa_03
import into: osgi_jaxrs_03a

From osgi_jpa_03, exporting the model package

showing manifest.ms source
Manifest-Version: 1.0
Bundle-Blueprint: OSGI-INF/blueprint/*.xml
Bundle-Version: 1.0.0
Bundle-Name: osgi_jpa_03
Bundle-ManifestVersion: 2
Import-Package: javax.persistence;version="1.1.0",
 javax.sql;version="0.0.0",
 javax.transaction;version="1.1.0",
 javax.xml.bind.annotation
Meta-Persistence:
Bundle-SymbolicName: osgi_jpa_03
Bundle-RequiredExecutionEnvironment : JavaSE-1.6
Export-Package: model


Import the model package into the osgi_jaxrs_03a (our JAX-RS project)


NOTE: Also include package javax.naming

manifest.ms for osgi_jaxrs_03a
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: osgi_jaxrs_03a
Bundle-SymbolicName: osgi_jaxrs_03a
Bundle-Version: 1.0.0
Bundle-ClassPath: WEB-INF/classes
Bundle-RequiredExecutionEnvironment : JavaSE-1.6
Web-ContextPath: /osgi_jaxrs_03a
Import-Package: com.ibm.websphere.jaxrs.server;version="1.0.0",
 javax.el;version="2.0",
 javax.naming,
 javax.servlet;version="2.5",
 javax.servlet.annotation,
 javax.servlet.http;version="2.5",
 javax.servlet.jsp;version="2.0",
 javax.servlet.jsp.el;version="2.0",
 javax.servlet.jsp.tagext;version="2.0",
 javax.ws.rs;version="1.0.0",
 javax.ws.rs.core;version="1.0.0",
 javax.ws.rs.ext;version="1.0.0",
 javax.xml.bind.annotation,
 model


Create the List container to hold results from queries to JPA color model 

Source: 
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

import model.Color;


@XmlRootElement(name="colorlist" )
public class ColorList {

     private List<Color> colorlist = new ArrayList<Color>();
     
     @XmlElement(name = "items")
     public List<Color> getColorList() {
            return colorlist;
     }
     
     public void setColorList(List<Color> list) {
            this. colorlist = list;
     }
     
}



Create the ColorModelService interface
Source: 
package colorservice;

import model.ColorManager; // imported from the JPA project

public interface ColorModelService {
     
     public ColorManager getColorManager();

     public void setColorManager(ColorManager colorManager);
     
     public ColorList getColorsSTUB();
     
     public ColorList getColors();
     
}


Create the ColorModelServiceImpl
source: 
package colorservice;

import java.util.ArrayList;
import java.util.List;

import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;

import model.Color;
import model.ColorManager;

@Path(value = "/colorservice")
public class ColorModelServiceImpl implements ColorModelService {

     // private ColorManager colorManager = null;
     // Trying a static property - not sure that I'd use this for a 'real' application.
     //   see other options below under 'getColoManager()'
     private static ColorManager colorManager = null;
     
     public ColorModelServiceImpl() {
           System. out.println( "*** ColorModelServiceImpl()");
     }

     public void startUp() {
           System. out.println( "*** ColorModelServiceImpl.startUp CALLED");
     }
     
     public void shutdown() {
           System. out.println( "*** ColorModelServiceImpl.shutdown CALLED");
           System. out.println( "*** setting colorManager to NULL");
           ColorModelServiceImpl. colorManager = null;
     }
     
     public ColorManager getColorManager() {
           
            if (ColorModelServiceImpl. colorManager == null) {
                System. out.println( "*** ColorModelServiceImpl.getColors().colorManager is NULL! ");
           }
           
            // ----------------------
           
            if (ColorModelServiceImpl. colorManager == null) {
                System. out.println( "*** Setting colorManager with osgi service lookup");
                 try {
                      InitialContext ic = new InitialContext();
                       // this.colorManager = (ColorManager) ic.lookup("osgi:service/model.ColorManager");
                      
                       // The next two methods of lookup work with Liberty v8.5.0.2
                       // this.colorManager = (ColorManager) ic.lookup("osgi:service/"+ColorManager.class.getName());
                      ColorModelServiceImpl. colorManager = (ColorManager) ic.lookup("blueprint:comp/colormanagerservice" );
                } catch (NamingException e) {
                       e.printStackTrace();
                } catch (Exception e) {
                      e.printStackTrace();
                }
           }
           
            // ----------------------
            return colorManager;
     }

     public void setColorManager(ColorManager colorManager) {
           System. out.println( "*** ColorModelServiceImpl.setColorManager()");
           ColorModelServiceImpl. colorManager = colorManager;
     }
     
     @Override
     @GET
     @Path("stub")
     @Produces("application/json")
     public ColorList getColorsSTUB() {
           
           ColorList colorList = new ColorList();
           List<Color> list = new ArrayList<Color>();

           list.add( new Color( "blue", "blue"));
           list.add( new Color( "green", "green"));
           list.add( new Color( "purple", "purple"));

           colorList.setColorList(list);

            return colorList;
     }
     
     @Override
     @GET
     @Path("getcolors")
     @Produces("application/json")
     public ColorList getColors() {
           
           ColorManager cMgr = getColorManager();
           List<Color> list = cMgr.getColor();
           ColorList colorList = new ColorList();
           colorList.setColorList(list);
           
            return colorList;
     }
     
}

---------------------------------------------
ColorModelServiceImpl Review: 
NOTE: Only covering the interesting bits
---------------------------------------------


private static ColorManager colorManager = null;

Both CXF and Wink (JAX-RS implementations) create a new ColorModuleServiceImpl per each invocation. Though I've read of a few methods, via blueprint, in guiding proper managed startup... I haven't been able to make them work. I listed three work-arounds in source:

1) use a static colorManager property
2) InitialContext().lookup("osgi:service/model.ColorManager")
3) InitialContext().lookup("blueprint:comp/colormanagerservice")

#3 is the IBM's recommended approach

I choose #1 for simplicity - though, I probably wouldn't go with this approach normally and prefer to pull instances from some sort of a managed pool of ready connections. 

------------------------------------------------
public ColorManager getColorManager()

Normally this simply returns the static property colorManager. Earlier however, I was having some trouble getting Wink to use my "officially" blueprint managed ColorModelService instance. The method's details illustrates other methods for working around object lookup. 

------------------------------------------------
public void setColorManager(ColorManager colorManager) 

Blueprint requires the setter for dependency wiring. As blueprint creates a "managed" bean, this property is automatic set via "property reference" (see below details under "blueprint").


------------------------------------------------
public ColorList getColorsSTUB () 

This test STUB returns a fully constructed color list without needing a JPA connection into our database. 

      public ColorList getColorsSTUB() {
           ColorList colorList = new ColorList();
           List<Color> list = new ArrayList<Color>();

           list.add( new Color( "blue", "blue"));
           list.add( new Color( "green", "green"));
           list.add( new Color( "purple", "purple"));

           colorList.setColorList(list);

            return colorList;
          }

------------------------------------------------
public ColorList getColors()

The primary responsibility for this class is to fetch colors from the database via JPA

     public ColorList getColors() {
           
           ColorManager cMgr = getColorManager(); // gets a reference to the color manager (JPA entity wrapper)
           List<Color> list = cMgr.getColor(); // fetch a list of color entities 
           ColorList colorList = new ColorList(); // create ColorList wrapper - required for JSON/XML construction
           colorList.setColorList(list); // set list into the container
           
            return colorList;
     }



1a) Configure Blueprint

Add ColorModelServiceImpl.class to AppService

package colorservice;

import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.core.Application;

public class AppService extends Application {
     @Override
     public Set<Class<?>> getClasses() {
           Set<Class<?>> classes = new HashSet<Class<?>>();
            // URL http://babe:9080/osgi_jaxrs_03a/jaxrs/servicetest
           classes.add(ServiceTest. class);
            // http://babe:9080/osgi_jaxrs_03a/jaxrs/colorservice/stub
            // http://babe:9080/osgi_jaxrs_03a/jaxrs/colorservice/getcolors
           classes.add(ColorModelServiceImpl.class);

            return classes;
     }
}



2) Configure Blueprint


Create blueprint.xml
right-click project -> select "other" -> filter on "bue" -> select Blueprint File"
-> Next



New Blueprint File
Select default location for this OSGi type of project 
"osgi_jaxrs_03a/WebContent/OSGI-INF/blueprint"
-> next


Add blueprint namespaces
-> Finish


Create a "Bean"
Select "Blueprint" -> click "add"


Add a Bean
Select "Bean" click "OK"


New Blueprint Bean
click "Browse" -> filter on "colorservice." -> select ColorModelServiceImpl from osgi_jaxrs_03a project
NOTE: Make sure you select the class from the correct project !




Create new blueprint bean
Leave default recommendation for Bean ID
-> OK


Bean Created




Create Reference
Select "blueprint" -> click "add"



Select Reference
Select "Reference" -> click "OK" 



Select Interface to Reference
Don't forget we're adding a reference into osgi_jaxrs_03a (JAX-RS) project
-- We're referencing an interface within the osgi_jpa_03 (JPA) project

Click "Browse" -> select ColorManager interface from osgi_jpa_03 project
-> OK



Leave Component name blank!



Bean and Reference created from osgi_jaxrs_03a project



Reviewing references 

The bean class points to colorservice.colorModelServiceImpl
The reference interface points to model.ColorManager interface within osgi_jpa_03 project
Property colorManager points to reference ColorModelServiceImplBeanReference



Create a Property for ColorModelServiceImplBean
Select ColorModelServiceImplBean -> click Add
-> Select Property -> click OK



Set Property Details
select the property we just created -> Details Reference Browse ->
-> select Reference: ColorModelServiceImplBeanReference -> OK





Set Property Details (continued)
Set Name -> colorManager
NOTE: "colorManager" the property from class ColorModelServiceImpl (see above code review)


Blueprint property requires a setter to set value (wire) ColorManager to ColorModelService (ReST API)


Create Reference Listener for ColoModelServiceImplBeanReference
Select referecne -> click "add" -> select Reference listener
-> OK



Fill in Reference Listener Details
Click Browse -> select Reference (created above) -> OK


Reference Listener Method References
Fill in method names:
Bind: referenceBind
Unbind: referenceUnBind



Reference Listener methods point to ColorManagerImpl methods (from JPA project)






3) Create OSGi Application and Deploy to Liberty Server

Create OSGi Application Project
Add projects:  
- osgi_jpa_03 (jpa project)
- osgi_jaxrs_03a (JAX-RS project)




Deploy project to Liberty Server and Start


Log output: messages.log



Right-click service and copy/paste url into browser



Test Works



==============
DONE
==============